#ifndef __PARSER_H__
#define __PARSER_H__

#include <string>
#include <vector>

using namespace std;

struct SpefConnection;
struct SpefCapacitance;
struct SpefResistance;
struct LibParserCellInfo;
struct LibParserLUT;
struct LibParserTimingInfo;
struct LibParserPinInfo;
class Dumper;

class cellInst_C
{
    public:
        cellInst_C(string p_strCellType,string p_strCellInst,vector<std::pair<string,string> >& p_vPinNetPair)
            : _strCellType(p_strCellType), _strCellInst(p_strCellInst), _pairPinNet(p_vPinNetPair) {}
        //Accessor
        string getCellType() const {return _strCellType;}
        string getCellInst() const {return _strCellInst;}
        const vector<std::pair<string, string> >& getPinNetPair() const {return _pairPinNet;}
    
    private:
        string _strCellType;
        string _strCellInst;
        vector<std::pair<string, string> > _pairPinNet;
};

class module_C
{
    public:
        module_C(string p_strName):_strName(p_strName) {}
        //Accessor
        string getName() const {return _strName;}
        const vector<string>& getPI() const {return _vPI;}
        const vector<string>& getPO() const {return _vPO;}
        const vector<string>& getNet() const {return _vNet;}
        const vector<cellInst_C*>& getCellInst() const {return _vCellInst;}
        //Modifier - init
        void addPI(string p_strName) {_vPI.push_back(p_strName);}
        void addPO(string p_strName) {_vPO.push_back(p_strName);}
        void addNet(string p_strName) {_vNet.push_back(p_strName);}
        void addInst(cellInst_C* p_pCellInst) {_vCellInst.push_back(p_pCellInst);}
    
    private:
        string               _strName;
        vector<string>       _vPI;
        vector<string>       _vPO;
        vector<string>       _vNet;
        vector<cellInst_C*>  _vCellInst;
};

struct inputDriver_S
{
    public:
       string _strCell; 
       string _strPin;
       float  _fTransRise;
       float  _fTransFall;
};

struct clkData_S
{
    public:
        string _strClockName;
        string _strClockPort;
        float  _fClockPeriod;
};

struct sdcData_S
{
    public:
        clkData_S*                                  _pClkData;
        vector<std::pair<string,float> >            _vInputDelayPair;
        vector<std::pair<string,inputDriver_S*> >   _vInputDrive;
        vector<std::pair<string,float> >            _vOutputDelayPair;
        vector<std::pair<string,float> >            _vOutputLoadPair;
};

struct spefData_S
{
    public:
        string                   _strNetName;
        float                    _fLumpedCap;
        vector<SpefConnection>  _vConnection;
        vector<SpefCapacitance> _vCap;
        vector<SpefResistance>  _vRes;
};

struct ParserData_S
{
    public:
        vector<module_C*>           _vModule;
        sdcData_S*                  _pSdcData;
        vector<spefData_S*>         _vSpefData;
        float                       _fCellMaxTrans;
        vector<LibParserCellInfo>   _vCellLibrary;
};

class Parser_C
{
    public:
        Parser_C(string p_strDir,string p_strBenchMarkName);
        void parse();
        ParserData_S* getData() const {return _pData;}
        void dumpModule(); 
        void dumpSDC();
        void dumpSPEF();
        void dumpLibrary();

    private:
        void parseVerilog(string p_strFileName);
        void parseSdc(string p_strFileName);
        void parseSpef(string p_strFileName);
        void parseLibrary(string p_strFileName);
        void dumpLUT(Dumper& p_rDumper,const LibParserLUT& p_rLUT,const char* p_caTimingName);
        void dumpTimingInfo(Dumper& p_rDumper,const LibParserTimingInfo& p_rTimingInfo);
        void dumpPinInfo(Dumper& p_rDumper,const LibParserPinInfo& p_rPinInfo);
        
        string _strDir;
        string _strBenchMarkName;
        ParserData_S* _pData;
};

#endif

